﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.IO;

namespace winpackman
{

    public partial class FRMmain : Form
    {
        public FRMmain()
        {
            InitializeComponent();
        }

        winpackman_class main_class = new winpackman_class();
        string version = (System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.Major.ToString()) + "." + (System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.Minor.ToString());
        WebClient client = new WebClient();
        const int CATEGORY_ALL = -1;
        public Color querycolor = Color.FromArgb(174, 255, 180);

        int CURRENT_CATEGORY = CATEGORY_ALL;

        public void loadCategoryList()
        {
            LSTcategory.Items.Clear();
            foreach (string category in main_class.categoryID.Keys)
            {
                LSTcategory.Items.Add(category);
            }
        }

        public void loadCategory()
        {
            loadCategory(CURRENT_CATEGORY);
        }
        public void loadCategory(int ID)
        {
            LSTpackages.Items.Clear();
            foreach (Software app in main_class.Softwarelist.Values)
            {
                if (((app.categoryID == ID.ToString()) || (ID == CATEGORY_ALL)) &&
                    (((main_class.OS_Bits == "x86") && app.x86.available) || (main_class.OS_Bits == "x64")) &&
                    ((app.VersionType == "") || (main_class.config.viewbeta== true))
                    )
                {
                    ListViewItem lvi = new ListViewItem(app.Name);
                    if (app.Installed != "")
                        lvi.BackColor = Color.Green;
                    if (main_class.Installlist.ContainsKey(int.Parse(app.packageID)))
                        lvi.BackColor = querycolor;
                    if (app.VersionType != "")
                        lvi.ForeColor = Color.Plum;
                    lvi.SubItems.Add(app.Version);
                    lvi.ToolTipText = app.Name + ":\n" + app.Description;
                    if (app.VersionType != "") lvi.ToolTipText += "\n\n" + app.VersionType;
                    lvi.SubItems.Add(app.filetype);
                    lvi.SubItems.Add(app.Installed);
                    lvi.Tag = app.packageID;
                    LSTpackages.Items.Add(lvi);
                }
            }
            LBLcount.Text = "Packages: " + LSTpackages.Items.Count; 
        }

        void loadpackagefile(bool update)
        {
            dataupdate form = new dataupdate();
            form.main_class = main_class;
            form.load = !update;
            form.ShowDialog();
            loadCategoryList();
            loadCategory();
            loadQueryList();
            if (update) LBLupdateTime.Text = "Last update: " + main_class.lastupdate;
            LBLupdateTime.ToolTipText = "Load time:\t" + main_class.updatetime + "ms\n";
            cachesize();
        }

        private void FRMmain_Load(object sender, EventArgs e)
        {
            main_class.load();
            main_class.loadconfig();
            switch (IntPtr.Size)
            {
                case 4:
                    main_class.OS_Bits = "x86";
                    break;
                case 8:
                    main_class.OS_Bits = "x64";
                    break;
            }
            this.Text += " " + version + " " + main_class.OS_Bits;
            if (main_class.debug.specialdownload || main_class.debug.md5out || main_class.debug.downloadonly)
                this.Text += " - #### DEBUG ###";
            loadpackagefile(false);
        }

        private void BTNreload_Click(object sender, EventArgs e)
        {
            loadpackagefile(true);
        }

        private void LSTcategory_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (LSTcategory.SelectedIndex != -1)
            {
                CURRENT_CATEGORY = main_class.categoryID[LSTcategory.Text];
                loadCategory();
            }
        }

        private void updatePackageListToolStripMenuItem_Click(object sender, EventArgs e)
        {
            loadpackagefile(true);
        }

        private void quitWinapticToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void toolStripButton1_Click(object sender, EventArgs e)
        {
            if (main_class.Installlist.Count > 0)
            {
                DialogResult result = MessageBox.Show("Accept End-user licence agreement of all packages?", "Accept EULA", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                if (result == System.Windows.Forms.DialogResult.Yes)
                {
                    foreach (InstallSoftware app in main_class.Installlist.Values)
                    {
                        app.DownloadPercentage = 0;
                        app.InstallPercentage = 0;
                        app.Status = "Waiting";
                    }
                    FRMapply apply = new FRMapply();
                    apply.main_class = main_class;
                    apply.ShowDialog();
                    if (main_class.config.clearqueryinstall)
                    {
                        main_class.Installlist.Clear();
                        loadQueryList();
                        loadCategory();
                    }
                }
                else
                    MessageBox.Show("Sorry, you must agree to the End-user license agreement.\n\tInstallation is aborted.", "EULA Error", MessageBoxButtons.OK, MessageBoxIcon.Stop);
            }
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            (new AboutBox1()).ShowDialog();
        }

        private void settingsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            FRMsettings settings = new FRMsettings();
            settings.main_class = main_class;
            settings.ShowDialog();
            loadCategory();
            loadQueryList();
        }

        public void loadQueryList()
        {
            LSTque.Items.Clear();
            foreach (InstallSoftware app in main_class.Installlist.Values)
            {
                Software appdata = main_class.Softwarelist[app.MemberOf];
                ListViewItem lvi = new ListViewItem(appdata.Name);
                lvi.SubItems.Add(appdata.Version);
                lvi.SubItems.Add(app.Architecture);
                lvi.SubItems.Add(main_class.Lang_2toEng[app.Language]);
                LSTque.Items.Add(lvi);
            }
            if (main_class.Installlist.Count > 0) toolStripButton1.Enabled = true;
            else toolStripButton1.Enabled = false;
        }

        private void savePackagescriptToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (main_class.Installlist.Count > 0)
            {
                if (saveFileDialog1.ShowDialog() == DialogResult.OK)
                {
                    Stream myStream;
                    if ((myStream = saveFileDialog1.OpenFile()) != null)
                    {
                        StreamWriter wText = new StreamWriter(myStream);
                        foreach (KeyValuePair<int,InstallSoftware> app in main_class.Installlist)
                        {
                            wText.WriteLine(app.Value.MemberOf.ToString() + ";" + app.Value.Language + ";" + app.Value.Architecture);
                        }
                        wText.Close();
                        myStream.Close();
                    }
                    else MessageBox.Show("Can't write to file", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }

        private void openPackagescriptToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                main_class.Installlist.Clear();
                foreach (String packagesID in File.ReadAllLines(openFileDialog1.FileName))
                {
                    String[] part = packagesID.Trim().Split(";".ToCharArray());
                    if ((part[2] == "x64") && (main_class.OS_Bits == "x86"))
                        part[2] = "x86";
                    addtoque(int.Parse(part[0]), part[1], part[2]);
                }
                loadQueryList();
                loadCategory();
            }
        }

        private void CTXpackage_Opening(object sender, CancelEventArgs e)
        {
            if (LSTpackages.SelectedItems.Count > 0)
            {
                CTXpackage.Items.Clear();
                if (!main_class.Installlist.ContainsKey(main_class.NameToID[LSTpackages.SelectedItems[0].Text]))
                {
                    Software app = main_class.Softwarelist[main_class.NameToID[LSTpackages.SelectedItems[0].Text]];
                    if (app.x86.available &&
                        (((main_class.OS_Bits == "x64") && app.x64.available && !main_class.config.hidex86) || (main_class.OS_Bits == "x86") || !app.x64.available))
                    {
                        ToolStripMenuItem newItem = new ToolStripMenuItem("x86");
                        if ((app.x86.Language.Count != 1) || !app.x86.Language.ContainsKey("en"))
                        {
                            foreach (String Language in app.x86.Language.Keys)
                            {
                                ToolStripMenuItem Item = new ToolStripMenuItem(main_class.Lang_2toEng[Language]);
                                Item.Name = app.packageID + ";x86;" + Language;
                                Item.Click += new EventHandler(MenuItemClickHandler);
                                newItem.DropDownItems.Add(Item);
                            }
                        }
                        else
                        {
                            newItem.Text = "x86 - " + main_class.Lang_2toEng["en"];
                            newItem.Name = app.packageID + ";x86;en";
                            newItem.Click += new EventHandler(MenuItemClickHandler);
                        }
                        CTXpackage.Items.Add(newItem);
                    }
                    if ((main_class.OS_Bits == "x64") && app.x64.available)
                    {
                        ToolStripMenuItem newItem = new ToolStripMenuItem("x64");
                        if ((app.x64.Language.Count != 1) || !app.x64.Language.ContainsKey("en"))
                        {
                            foreach (String Language in app.x64.Language.Keys)
                            {
                                ToolStripMenuItem Item = new ToolStripMenuItem(main_class.Lang_2toEng[Language]);
                                Item.Name = app.packageID + ";x64;" + Language;
                                Item.Click += new EventHandler(MenuItemClickHandler);
                                newItem.DropDownItems.Add(Item);
                            }
                        }
                        else
                        {
                            newItem.Text = "x64 - " + main_class.Lang_2toEng["en"];
                            newItem.Name = app.packageID + ";x64;en";
                            newItem.Click += new EventHandler(MenuItemClickHandler);
                        }
                        CTXpackage.Items.Add(newItem);
                    }
                }
                else
                {
                    ToolStripMenuItem Item = new ToolStripMenuItem("Remove from install list");
                    Item.Click += new EventHandler(MenuItemClickHandler);
                    CTXpackage.Items.Add(Item);
                }
            }
        }
        private void MenuItemClickHandler(object sender, EventArgs e)
        {
            ToolStripMenuItem clickedItem = (ToolStripMenuItem)sender;
            if (!main_class.Installlist.ContainsKey(main_class.NameToID[LSTpackages.SelectedItems[0].Text]))
            {
                int selecteditem = LSTpackages.SelectedItems[0].Index;
                String[] MenuItem = clickedItem.Name.Split(";".ToCharArray());
                if (addtoque(Int32.Parse(MenuItem[0]), MenuItem[2], MenuItem[1]))
                {
                    LSTpackages.Items[selecteditem].BackColor = querycolor;
                }
            }
            else
            {
                String[] MenuItem = clickedItem.Name.Split(";".ToCharArray());
                main_class.Installlist.Remove(main_class.NameToID[LSTpackages.SelectedItems[0].Text]);
                LSTpackages.SelectedItems[0].BackColor = SystemColors.Window;
            }
            if (LSTpackages.SelectedItems.Count > 0)
                LSTpackages.SelectedItems[0].Selected = false;
            loadQueryList();
        }

        private void LSTque_DoubleClick(object sender, EventArgs e)
        {
            if (LSTque.SelectedItems.Count > 0)
            {
                main_class.Installlist.Remove((main_class.NameToID[LSTque.SelectedItems[0].Text]));
                loadQueryList();
                loadCategory();
            }
        }

        private void LSTpackages_DoubleClick(object sender, EventArgs e)
        {
            if (LSTpackages.SelectedItems.Count > 0)
            {
                int selecteditem = LSTpackages.SelectedItems[0].Index;
                int ID = main_class.NameToID[LSTpackages.SelectedItems[0].Text];
                if (!main_class.Installlist.ContainsKey(ID))
                {
                    if (addtoque(ID))
                    {
                        LSTpackages.Items[selecteditem].BackColor = querycolor;
                    }
                }
                else
                {
                    main_class.Installlist.Remove(ID);
                    LSTpackages.Items[selecteditem].BackColor = SystemColors.Window;
                }
                if (LSTpackages.SelectedItems.Count > 0)
                    LSTpackages.SelectedItems[0].Selected = false;
                loadQueryList();
            }
        }

        private void clearQueryToolStripMenuItem_Click(object sender, EventArgs e)
        {
            main_class.Installlist.Clear();
            loadCategory();
            loadQueryList();
        }

        bool Dependencytest(int packid)
        {
            Software app = main_class.Softwarelist[packid];
            bool test = true;
            string missing = "";
            int[] missingid = { };
            if (app.Dependency[0] != 0)
            {
                foreach (int depen in app.Dependency)
                {
                    if (main_class.Softwarelist[depen].Installed == "" && !main_class.Installlist.ContainsKey(depen))
                    {
                        test = false;
                        missing += "\n" + main_class.Softwarelist[depen].Name;
                        Array.Resize(ref missingid, missingid.Length + 1);
                        missingid[missingid.Length - 1] = depen;
                    }
                }
            }
            if (test == false)
            {
                DialogResult result = MessageBox.Show("Missing:" + missing + "\n\n Install it?", "Dependency failure", MessageBoxButtons.YesNo, MessageBoxIcon.Stop);
                if (result == DialogResult.Yes)
                {
                    foreach (int item in missingid)
                        addtoque(item);
                    loadQueryList();
                    loadCategory();
                    test = true;
                }
            }
            return test;
        }

        void cachesize()
        {
            string[] files = { "Cache/packages.list", "Cache/category.list", "Cache/config.xml" };
            Array.Resize(ref files, main_class.config.Language.Length + 3);
            int count = 3;
            foreach (string lang in main_class.config.Language)
                files[count++] = "Cache/pack_" + lang + ".list";
            long winpackmandata = 0;
            foreach (string file in files)
            {
                if (File.Exists(file))
                    winpackmandata += new FileInfo(file).Length;
            }
            long all = 0;
            files = Directory.GetFiles("Cache/", "*.*");
            foreach (string file in files)
            {
                all += new FileInfo(file).Length;
            }
            LBLupdateTime.ToolTipText += "Packages data:\t" + (winpackmandata / 1024) + "KB\nAll cache data:\t" + (all / 1024) + "KB";
        }

        bool addtoque(int ID)
        {
            string architecture = "";
            Software app = main_class.Softwarelist[ID];
            if (((main_class.OS_Bits == "x86") || ((main_class.OS_Bits == "x64") && !app.x64.available)) && app.x86.Language.ContainsKey("en"))
                architecture = "x86";
            else if ((main_class.OS_Bits == "x64") && (app.x64.Language.ContainsKey("en")))
                architecture = "x64";
            if (architecture != "") return addtoque(ID, "en", architecture);
            else return false;
        }

        bool addtoque(int ID, string language, string architecture)
        {
            if (!main_class.Installlist.ContainsKey(ID))
            {
                if (Dependencytest(ID))
                {
                    Software app = main_class.Softwarelist[ID];
                    InstallSoftware newItem = new InstallSoftware();
                    newItem.Name = app.Name;
                    newItem.Language = "en";
                    newItem.MemberOf = ID;
                    newItem.Architecture = architecture;
                    switch (architecture)
                    {
                        case "x86":
                            newItem.install = app.x86.Language[language];
                            break;
                        case "x64":
                            newItem.install = app.x64.Language[language];
                            break;
                    }
                    main_class.Installlist.Add(ID, newItem);
                    return true;
                }
                else return false;
            }
            else return false;
        }
    }
}
